package protocol.command;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import protocol.command.request.LoginRequestPacket;
import protocol.command.request.MessageRequestPacket;
import protocol.command.response.LoginResponsePacket;
import protocol.command.response.MessageResponsePacket;
import serialize.Serializer;
import serialize.impl.JSONSerializer;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xiaozefeng
 * @date 2018/12/2 下午12:36
 */
public class PacketCodeC {

    public static final int MAGIC_NUMBER = 0x12345678;

    private final Map<Byte, Class<? extends Packet>> packetTypeMap;

    private final Map<Byte, Serializer> serializerMap;

    public static final PacketCodeC INSTANCE = new PacketCodeC();

    private PacketCodeC() {
        packetTypeMap = new HashMap<>();
        packetTypeMap.put(Command.LOGIN_REQUEST, LoginRequestPacket.class);
        packetTypeMap.put(Command.LOGIN_RESPONSE, LoginResponsePacket.class);
        packetTypeMap.put(Command.MESSAGE_REQUEST, MessageRequestPacket.class);
        packetTypeMap.put(Command.MESSAGE_RESPONSE, MessageResponsePacket.class);

        serializerMap = new HashMap<>();
        Serializer serializer = new JSONSerializer();
        serializerMap.put(serializer.getSerializerAlgorithm(), serializer);
    }


    public ByteBuf encode(ByteBufAllocator byteBufAllocator, Packet packet) {
        // 1. 创建ByteBuf 对象
        ByteBuf byteBuf = byteBufAllocator.ioBuffer();

        //// 2. 序列化对象
        //byte[] bytes = Serializer.DEFAULT.serialize(packet);
        //
        //// 3. 实际编码过程
        //byteBuf.writeInt(MAGIC_NUMBER);
        //byteBuf.writeByte(packet.getVersion());
        //byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        //byteBuf.writeByte(packet.getCommand());
        //byteBuf.writeInt(bytes.length);
        //byteBuf.writeBytes(bytes);
        //
        //return byteBuf;
        return encode(byteBuf, packet);
    }

    public ByteBuf encode(ByteBuf byteBuf, Packet packet) {

        // 2. 序列化对象
        byte[] bytes = Serializer.DEFAULT.serialize(packet);

        // 3. 实际编码过程
        byteBuf.writeInt(MAGIC_NUMBER);
        byteBuf.writeByte(packet.getVersion());
        byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        byteBuf.writeByte(packet.getCommand());
        byteBuf.writeInt(bytes.length);
        byteBuf.writeBytes(bytes);

        return byteBuf;
    }


    public Packet decode(ByteBuf byteBuf) {
        // skip magic number
        byteBuf.skipBytes(4);

        // skip version
        byteBuf.skipBytes(1);

        // 序列化算法
        byte serializeAlgorithm = byteBuf.readByte();

        // 指令
        byte command = byteBuf.readByte();

        // 实际数据包的长度
        int length = byteBuf.readInt();

        byte[] dst = new byte[length];
        byteBuf.readBytes(dst);


        Class<? extends Packet> requestType = getRequestType(command);
        Serializer serializer = getSerializer(serializeAlgorithm);

        if (requestType != null && serializer != null) {
            return serializer.deserialize(requestType, dst);
        }

        return null;
    }


    private Serializer getSerializer(byte serializeAlgorithm) {
        return serializerMap.get(serializeAlgorithm);
    }


    private Class<? extends Packet> getRequestType(byte command) {
        return packetTypeMap.get(command);
    }
}
